/**
 * 载入多个资源文件用此类
 * 顺序载入 封装载入配置资源
 * http://edn.egret.com/cn/article/index/id/119
 * 封装预加载【资源组】,加载同一组资源失败超过3次则失败
 * http://edn.egret.com/cn/article/index/id/121
 */
class ResManager extends BaseClass {
    //key=[groupName] , value = [回调function]
    private groups: any;
	
    //key=[groupName] , value = [失败次数]
    private errorTimes: any;
	
    //RES.loadConfig("resources/resource.json","resources/");  [resources/resource.json,resources/]
    private configs: Array<any>;
    private onConfigComplete: Function;
    private onConfigCompleteTarget: any;
	
    /** 重试三次 */
    private static ERROR_GROUP_TIMES = 3;


    public constructor() {
        super();
        this.groups = {};
        this.errorTimes = {};
        this.configs = new Array<any>();
        /** 监听器常驻内存，仅有一个实例，分发给各回调Function */
        RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE,this.onResourceLoadComplete,this);
        RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS,this.onResourceProgress,this);
        RES.addEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR,this.onResourceLoadError,this);
    }

    public static get get(): ResManager {
        return ResManager.getInstance();
    }
	
    /**
     * 添加配置文件 
     * @param jsonPath 比如：resource/resource.json
     * @param filePath 比如：resource/
     */
    public addConfig(jsonPath: string,filePath: string): void {
        this.configs.push([jsonPath,filePath]);
    }
    
    /**
     * 真正加载配置资源文件
     * @param onConfigComplete 
     * @param onConfigCompleteTarget
     */
    public loadConfig(onConfigComplete: Function,onConfigCompleteTarget: any) {
        this.onConfigComplete = onConfigComplete;
        this.onConfigCompleteTarget = onConfigCompleteTarget;
        this.loadNextConfig();
    }
    
    /**
     * 加载资源组，一般在加载完配置资源后开始载入
     */
    public loadGroup(groupName: string,onResourceLoadComplete: Function,onResourceProgress: Function,onResourceLoadTarget: any): void {
        this.groups[groupName] = [onResourceLoadComplete,onResourceProgress,onResourceLoadTarget];
        this.errorTimes[groupName] = 0;
        ////Log.n();
        ////Log.d("Group:\"" + groupName + "\",LoadStart");
        RES.loadGroup(groupName);
    }
    /**
     * 加载资源，可以处理error的问题
     */ 
    public loadAllGroup(groupName: string,onResourceLoadComplete: Function,onResourceProgress: Function,onResourceErrorRetry: Function,onResourceLoadTarget: any): void {
        this.groups[groupName] = [onResourceLoadComplete,onResourceProgress,onResourceErrorRetry,onResourceLoadTarget];
        this.errorTimes[groupName] = 0;
        RES.loadGroup(groupName);
    }
    
    /**
     * 开始加载配置
     */
    private loadNextConfig(): void {
        //加载完成
        if(this.configs.length == 0) {
            this.onConfigComplete.call(this.onConfigCompleteTarget);
            this.onConfigComplete = null;
            this.onConfigCompleteTarget = null;
            return;
        }
        var arr: any = this.configs.shift();
        RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigCompleteHandle,this);
        RES.addEventListener(RES.ResourceEvent.CONFIG_LOAD_ERROR,this.onConfigLoadErrHandle,this);
        //Log.d("Load Config,url:" + arr[0] + ",resourceRoot:" + arr[1]);
        RES.loadConfig(arr[0],arr[1]);
    }

    private onConfigCompleteHandle(event: RES.ResourceEvent): void {
        RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigCompleteHandle,this);
        this.loadNextConfig();
    }

    private onConfigLoadErrHandle(event: RES.ResourceEvent): void {
        RES.removeEventListener(RES.ResourceEvent.CONFIG_LOAD_ERROR,this.onConfigLoadErrHandle,this);
        //Log.e("config load error,res:" + event.groupName);
    }

    private onResourceLoadComplete(event: RES.ResourceEvent): void {
        var groupName = event.groupName;
        //Log.d("Group:\"" + groupName + "\",LoadComplete");
        if(this.groups[groupName] != null) {
            var callBack: any[] = this.groups[groupName];
            var onResourceLoadComplete: Function = callBack[0];
            var onResourceLoadTarget: Function = callBack[callBack.length - 1];
            if(onResourceLoadComplete != null) {
                onResourceLoadComplete.call(onResourceLoadTarget,groupName);
            }
            this.groups[groupName] = null;
            delete this.groups[groupName];
            this.errorTimes[groupName] = null;
            delete this.errorTimes[groupName];
        }
    }

    private onResourceProgress(event: RES.ResourceEvent): void {
        var groupName = event.groupName;
        //Log.d("Resource Load:\"" + groupName + "\",Progress:" + event.resItem);
        if(this.groups[groupName] != null) {
            var loadProgress: Function = this.groups[groupName][1];
            var loadProgressTarget: any = this.groups[groupName][2];
            if(loadProgress != null) {
                loadProgress.call(loadProgressTarget,event.itemsLoaded,event.itemsTotal);
            }
        }
    }

    private onResourceLoadError(event: RES.ResourceEvent): void {
        //加载失败
        var groupName = event.groupName;
        //Log.e("Group:\"" + groupName + "\",LoadError");
        var callBack: any[] = this.groups[groupName];
        var errorTimes: number = this.errorTimes[groupName];
        if(callBack != null && errorTimes != null && errorTimes >= ResManager.ERROR_GROUP_TIMES) {
            //如果设置了错误回调
            if(callBack.length == 4) {
                var onResourceErrorRetry: Function = callBack[callBack.length - 2];
                var onResourceLoadTarget: Function = callBack[callBack.length - 1];
                if(onResourceErrorRetry != null) {
                    onResourceErrorRetry.call(onResourceLoadTarget,groupName);
                }
            } else {
                //没有设置错误回调 
                //Log.d("Group:\"" + groupName + "\",Error! Retry Times:" + errorTimes);
                this.onResourceLoadComplete(event);
            }
        } else {
            if(errorTimes != null) {
                this.errorTimes[groupName]++;
            }
            //Log.d("Group:\"" + groupName + "\",Retry Load");
            RES.loadGroup(event.groupName);
        }
    }

}
